package main

import (
	"encoding/json"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
)

// User represents a user account
type User struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

// Word represents a vocabulary word
type Word struct {
	English string `json:"english"`
	Chinese string `json:"chinese"`
}

// WordManager manages words and users
type WordManager struct {
	users map[string]string // username -> password
	words []Word
	mu    sync.RWMutex
}

var wordManager = &WordManager{
	users: make(map[string]string),
	words: []Word{},
}

func init() {
	// Initialize with default user (username: pp, password: pp)
	wordManager.users["pp"] = "pp"
}

func main() {
	// Load words from file if exists
	wordManager.loadWords()

	// If no words loaded, initialize with all sample words
	if len(wordManager.words) == 0 {
		allWords := []Word{
			{English: "contempt", Chinese: "轻蔑"},
		}
		wordManager.words = allWords
		wordManager.saveWords()
	}

	// API endpoints
	http.HandleFunc("/api/login", loginHandler)
	http.HandleFunc("/api/words", wordsHandler)
	http.HandleFunc("/api/word", wordHandler)
	http.HandleFunc("/api/words/batch", batchDeleteHandler)

	// Serve static files
	http.Handle("/", http.FileServer(http.Dir("./static/")))

	log.Println("Server starting on :8088")
	log.Fatal(http.ListenAndServe(":8088", nil))
}

// loadWords loads words from a JSON file
func (wm *WordManager) loadWords() {
	data, err := os.ReadFile("words.json")
	if err != nil {
		// File doesn't exist, will be initialized with all sample words in main()
		return
	}

	var words []Word
	if err := json.Unmarshal(data, &words); err != nil {
		log.Printf("Error unmarshaling words: %v", err)
		return
	}

	wm.mu.Lock()
	wm.words = words
	wm.mu.Unlock()
}

// saveWords saves words to a JSON file
func (wm *WordManager) saveWords() {
	wm.mu.RLock()
	data, err := json.MarshalIndent(wm.words, "", "  ")
	wm.mu.RUnlock()

	if err != nil {
		log.Printf("Error marshaling words: %v", err)
		return
	}

	if err := os.WriteFile("words.json", data, 0644); err != nil {
		log.Printf("Error saving words: %v", err)
	}
}

// loginHandler handles user login
func loginHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	username := r.FormValue("username")
	password := r.FormValue("password")

	wordManager.mu.RLock()
	storedPassword, exists := wordManager.users[username]
	wordManager.mu.RUnlock()

	if !exists || storedPassword != password {
		http.Error(w, "Invalid username or password", http.StatusUnauthorized)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.Write([]byte("Login successful"))
}

// wordsHandler handles getting all words
func wordsHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodGet {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	wordManager.mu.RLock()
	words := wordManager.words
	wordManager.mu.RUnlock()

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(words)
}

// wordHandler handles adding a new word
func wordHandler(w http.ResponseWriter, r *http.Request) {
	// Check method
	if r.Method != http.MethodPost {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// Get word data
	english := strings.TrimSpace(r.FormValue("english"))
	chinese := strings.TrimSpace(r.FormValue("chinese"))

	// Validate input
	if english == "" || chinese == "" {
		http.Error(w, "English and Chinese fields are required", http.StatusBadRequest)
		return
	}

	// Add word at the beginning of the slice
	wordManager.mu.Lock()
	// Create a new slice with the new word at the beginning
	newWords := make([]Word, len(wordManager.words)+1)
	newWords[0] = Word{English: english, Chinese: chinese}
	copy(newWords[1:], wordManager.words)
	wordManager.words = newWords
	wordManager.mu.Unlock()

	// Save to file
	wordManager.saveWords()

	w.WriteHeader(http.StatusCreated)
	w.Write([]byte("Word added successfully"))
}

// batchDeleteHandler handles batch deleting words
func batchDeleteHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodDelete {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// Get words to delete from query parameters
	englishWords := r.URL.Query()["english"]

	if len(englishWords) == 0 {
		http.Error(w, "No words specified for deletion", http.StatusBadRequest)
		return
	}

	// Delete words
	wordManager.mu.Lock()
	var newWords []Word
	for _, word := range wordManager.words {
		found := false
		for _, english := range englishWords {
			if word.English == english {
				found = true
				break
			}
		}
		if !found {
			newWords = append(newWords, word)
		}
	}
	wordManager.words = newWords
	wordManager.mu.Unlock()

	// Save to file
	wordManager.saveWords()

	w.WriteHeader(http.StatusOK)
	w.Write([]byte("Words deleted successfully"))
}
